import 'dart:convert';
import 'dart:developer';

import 'package:bot_toast/bot_toast.dart';
import 'package:dio/dio.dart';
import 'package:elephantgas/bean/login_entity.dart';
import 'package:elephantgas/common/constant.dart';
import 'package:elephantgas/main.dart';
import 'package:elephantgas/network/h5_url.dart';
import 'package:elephantgas/routers/routers.dart';
import 'package:elephantgas/utils/toast_util.dart';
import 'package:elephantgas/utils/user_util.dart';
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';

class DioManager {
  static DioManager _instance;
  static DioManager getInstance() {
    if (_instance == null) {
      _instance = DioManager();
    }
    return _instance;
  }

  Dio dio = new Dio();
  DioManager() {
    dio.options.baseUrl = Constant.baseUrl;
    dio.options.connectTimeout = 15000;
    dio.options.receiveTimeout = 3000;
    dio.options.contentType = 'application/json; charset=utf-8';
    dio.options.responseType = ResponseType.json;
    dio.options.headers = {};
  }

  //get请求
  getRequest(String url, FormData params, Function successCallBack,
      Function errorCallBack) async {
    print(url);
    _requestHttp(url, successCallBack, 'get', "1", params, errorCallBack);
  }

  getRequest2(String url, FormData params, Function successCallBack,
      Function errorCallBack) async {
    print(url);
    _requestHttp(url, successCallBack, 'get', "2", params, errorCallBack);
  }

  //post请求
  post(String url, params, Function successCallBack,
      Function errorCallBack) async {
    _requestHttp(url, successCallBack, "post", "1", params, errorCallBack);
  }

  postJson(String url, params, Function successCallBack,
      Function errorCallBack) async {
    dio.options.contentType = 'application/json';
    _requestHttp(url, successCallBack, "post", "json", params, errorCallBack);
  }

  //delete请求
  delete(String url, params, Function successCallBack,
      Function errorCallBack) async {
    _requestHttp2(url, successCallBack, "delete", params, errorCallBack);
  }

  _requestHttp(String url, Function successCallBack,
      [String method, String type, params, Function errorCallBack]) async {
    if (type != "2") {
      BotToast.showLoading();
    }

    Response response;
    try {
      Options requestOptions = Options();
      Map<String, dynamic> _authorization = getAuthorizationHeader(url);
      if (_authorization != null) {
        // dio.options.merge(headers: _authorization);
        dio.options.headers = _authorization;
        // print('header~~~~~~~~~~~~~~: ' + dio.options.headers.toString());
        // print('options~~~~~~~~~~~~~~: ' + dio.options.contentType);
      }
      if (method == 'get') {
        if (params != null) {
          response = await dio.get(url,
              queryParameters: Map.fromEntries(params.fields),
              options: requestOptions);
        } else {
          response = await dio.get(url, options: requestOptions);
        }
      } else if (method == 'post') {
        if (type == 'json') {
          response = await dio.post(url, data: params, options: requestOptions);
        } else {
          if (params != null &&
              (params.fields.isNotEmpty || params.files.isNotEmpty)) {
            response =
                await dio.post(url, data: params, options: requestOptions);
          } else {
            response = await dio.post(url, options: requestOptions);
          }
        }
      }
    } on DioError catch (error) {
      //请求错误处理
      Response errorResponse;
      if (error.response != null) {
        errorResponse = error.response;
      } else {
        errorResponse = new Response(statusCode: 201);
      }

      //debug模式打印错误信息
      if (Constant.ISDEBUG) {
        print('请求url: ' + url);
        if (params != null && type!='json') {
          print('请求参数: ');
          for (int i = 0; i < params.fields.length; i++) {
            MapEntry<String, String> map = params.fields[i];
            print(map.key + '---' + map.value);
          }
        }else{
          print('请求json参数: ');
          print(json.encode(params));
        }
        print('请求异常' + error.toString());
        ErrorEntity eInfo = createErrorEntity(error);
        print(eInfo.message);
        // 错误提示
        // ToastUtil.show(eInfo.message);
      }
      _error(errorCallBack, error.message);
      return '';
    }

//    if (Constant.ISDEBUG) {
    print('请求url: ' + url);
    print('请求头: ' + dio.options.headers.toString());
    if (params != null && type != 'json') {
      print('请求参数: ');
      for (int i = 0; i < params.fields.length; i++) {
        MapEntry<String, String> map = params.fields[i];
        print(map.key + '---' + map.value);
      }
    } else {
      print('请求json参数: ');
      print(json.encode(params));
    }
    if (response != null) {
      print('返回json参数: ' + response.toString());
    }
//    }

    //返回结果
    BotToast.closeAllLoading();
    if (response.data == null || response.data == '') {
      if (response.statusCode == 200) {
        var instanceMap = Map();
        instanceMap['code'] = 0;
        successCallBack(instanceMap);
      } else {
        _error(errorCallBack, 'error');
      }
    } else {
      Map<String, dynamic> dataMap;
      try {
        String dataStr = json.encode(response.data);
        dataMap = json.decode(dataStr);
      } catch (e) {
        dataMap = json.decode(response.data);
      }

      if (dataMap == null || dataMap['code'] != 0) {
        print('dataMap code=='+dataMap['code'].toString() );
        if (dataMap['code'] == 2814) {
            if (UserUtil.getUseInfo()!=null) {
              UserUtil.loginout();
            }
            BuildContext context = navigatorKey.currentState.overlay.context;
            Routers.navigateTo(context, Routers.login,transition: TransitionType.inFromBottom,clearStack:true);

          return;
        }else if (dataMap['code'] == 2046) {
          BuildContext context = navigatorKey.currentState.overlay.context;
          ToastUtil.show(dataMap['message'] );
          // Routers.navigateTo(context, Routers.login,transition: TransitionType.inFromBottom);
          Routers.navigateTo(context, Routers.ele_webview, params: {
            'title': '我的',
            'param': '&id=' +
                UserUtil.getUseInfo()
                    .user
                    .userId+'&key=authStatus',
            'url': H5ServiceUrl.realName
          }).then((value) {
          });
          return;
        }
        _error(errorCallBack, dataMap['message'].toString());
      } else if (successCallBack != null) {
        successCallBack(dataMap);
      }
    }
  }

  _requestHttp2(String url, Function successCallBack,
      [String method, FormData params, Function errorCallBack]) async {
    BotToast.showLoading();
    Response response;
    try {
      Options requestOptions = Options();
      Map<String, dynamic> _authorization = getAuthorizationHeader(url);
      if (_authorization != null) {
        // dio.options.merge(headers: _authorization);
        dio.options.headers = _authorization;
        print('Token~~~~~~~~~~~~~~: ' + dio.options.headers.toString());
      }
      if (method == 'delete') {
        if (params != null &&
            (params.fields.isNotEmpty || params.files.isNotEmpty)) {
          response =
              await dio.delete(url, data: params, options: requestOptions);
        } else {
          response = await dio.delete(url, options: requestOptions);
        }
      }
    } on DioError catch (error) {
      //请求错误处理
      Response errorResponse;
      if (error.response != null) {
        errorResponse = error.response;
      } else {
        errorResponse = new Response(statusCode: 201);
      }

      //debug模式打印错误信息
      if (Constant.ISDEBUG) {
        print('请求异常' + error.toString());
        ErrorEntity eInfo = createErrorEntity(error);
        print(eInfo.message);
        // 错误提示
        // ToastUtil.show(eInfo.message);
      }
      _error(errorCallBack, error.message);
      return '';
    }

//    if (Constant.ISDEBUG) {
    print('请求url: ' + url);
    print('请求头: ' + dio.options.headers.toString());
    if (params != null) {
      print('请求参数: ');
      for (int i = 0; i < params.fields.length; i++) {
        MapEntry<String, String> map = params.fields[i];
        print(map.key + '---' + map.value);
      }
    }
    if (response != null) {
      print('返回参数: ' + response.toString());
    }
//    }
    BotToast.closeAllLoading();
    if (response.data == null || response.data == '') {
      if (response.statusCode == 200) {
        var instanceMap = Map();
        instanceMap['code'] = 200;
        successCallBack(instanceMap);
      } else {
        _error(errorCallBack, 'error');
      }
    } else {
      String dataStr = json.encode(response.data);
      print(dataStr);
      Map<String, dynamic> dataMap = json.decode(dataStr);
      if (dataMap == null || dataMap['code'] != 200) {
        // if (dataMap['code'] == 401) {
        //     if (UserUtil.isLogin()) {
        //       loginEventBus.fire(LoginEvent(false));
        //       UserUtil.loginout();
        //     }
        //     BuildContext context = navigatorKey.currentState.overlay.context;
        //     Routers.navigateTo(context, Routers.loginPage,transition: TransitionType.inFromBottom);

        //   return;
        // }
        _error(errorCallBack, dataMap['msg'].toString());
      } else if (successCallBack != null) {
        successCallBack(dataMap);
      }
    }
  }

  _error(Function errorCallBack, String error) {
    BotToast.closeAllLoading();
    if (errorCallBack != null) {
      print('errorCallBack');
      errorCallBack(error);
    }
  }

  /*
   * error统一处理
   */
  // 错误信息
  ErrorEntity createErrorEntity(DioError error) {
    switch (error.type) {
      case DioErrorType.cancel:
        {
          return ErrorEntity(code: -1, message: "请求取消");
        }
        break;
      case DioErrorType.connectTimeout:
        {
          return ErrorEntity(code: -1, message: "连接超时");
        }
        break;
      case DioErrorType.sendTimeout:
        {
          return ErrorEntity(code: -1, message: "请求超时");
        }
        break;
      case DioErrorType.receiveTimeout:
        {
          return ErrorEntity(code: -1, message: "响应超时");
        }
        break;
      case DioErrorType.response:
        {
          try {
            int errCode = error.response.statusCode;
            // String errMsg = error.response.statusMessage;
            // return ErrorEntity(code: errCode, message: errMsg);
            switch (errCode) {
              case 400:
                {
                  return ErrorEntity(code: errCode, message: "请求语法错误");
                }
                break;
              case 401:
                {
                  return ErrorEntity(code: errCode, message: "没有权限");
                }
                break;
              case 403:
                {
                  return ErrorEntity(code: errCode, message: "服务器拒绝执行");
                }
                break;
              case 404:
                {
                  return ErrorEntity(code: errCode, message: "无法连接服务器");
                }
                break;
              case 405:
                {
                  return ErrorEntity(code: errCode, message: "请求方法被禁止");
                }
                break;
              case 500:
                {
                  return ErrorEntity(code: errCode, message: "服务器内部错误");
                }
                break;
              case 502:
                {
                  return ErrorEntity(code: errCode, message: "无效的请求");
                }
                break;
              case 503:
                {
                  return ErrorEntity(code: errCode, message: "服务器挂了");
                }
                break;
              case 505:
                {
                  return ErrorEntity(code: errCode, message: "不支持HTTP协议请求");
                }
                break;
              default:
                {
                  // return ErrorEntity(code: errCode, message: "未知错误");
                  return ErrorEntity(
                      code: errCode, message: error.response.statusMessage);
                }
            }
          } on Exception catch (_) {
            return ErrorEntity(code: -1, message: "未知错误");
          }
        }
        break;
      default:
        {
          return ErrorEntity(code: -1, message: error.message);
        }
    }
  }

  Map<String, dynamic> getAuthorizationHeader(String url) {
    var headers;
    if (url.contains('user/oauth/token')) {
      headers = {
        'Authorization': 'Basic bXd4c2VydmljZToxMjM0NTY=',
        'Identifier': 'bXd4c2VydmljZTpvcmc6dXNlcjpyb2xl',
      };
      return headers;
    }

    String accessToken = UserUtil.getToken();
    Map userInfo = UserUtil.getUser();
    var digest1 = '', digest2 = '';
    if (userInfo != null) {
      digest1 = 'Bearer ' + accessToken;
      LoginData homeEntity = UserUtil.getUseInfo();
      var aa = 'mwxservice:' +
          homeEntity.user.authorities[0].orgId +
          ':' +
          homeEntity.user.userId +
          ':' +
          homeEntity.user.authorities[0].roles[0].roleId;
      var content2 = utf8.encode(aa);
      digest2 = base64Encode(content2);
    } else {}
    headers = {
      'Authorization': digest1,
      'Identifier': digest2,
    };
    return headers;
  }
}

// 异常处理
class ErrorEntity implements Exception {
  int code;
  String message;
  ErrorEntity({this.code, this.message});

  String toString() {
    if (message == null) return "Exception";
    return "Exception: code $code, $message";
  }
}
